home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / WindowMaker / util / setstyle.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-06-04  |  12.7 KB  |  583 lines

  1. /* setstyle.c - loads style related options to wmaker
  2.  *
  3.  *  WindowMaker window manager
  4.  * 
  5.  *  Copyright (c) 1997, 1998, 1999 Alfredo K. Kojima
  6.  * 
  7.  *  This program is free software; you can redistribute it and/or modify
  8.  *  it under the terms of the GNU General Public License as published by
  9.  *  the Free Software Foundation; either version 2 of the License, or
  10.  *  (at your option) any later version.
  11.  *
  12.  *  This program is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *  GNU General Public License for more details.
  16.  *
  17.  *  You should have received a copy of the GNU General Public License
  18.  *  along with this program; if not, write to the Free Software
  19.  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 
  20.  *  USA.
  21.  */
  22.  
  23.  
  24. #define PROG_VERSION "setstyle (Window Maker) 0.5"
  25.  
  26. #include <stdlib.h>
  27. #include <stdio.h>
  28. #include <proplist.h>
  29. #include <sys/stat.h>
  30. #include <unistd.h>
  31.  
  32. #include <X11/Xlib.h>
  33.  
  34. #include <string.h>
  35.  
  36. #include "../src/wconfig.h"
  37.  
  38. #define MAX_OPTIONS 128
  39.  
  40. char *FontOptions[] = {
  41.     "IconTitleFont",
  42.     "ClipTitleFont",
  43.     "DisplayFont",
  44.     "LargeDisplayFont",
  45.     "MenuTextFont",
  46.     "MenuTitleFont",
  47.     "WindowTitleFont",
  48.     NULL
  49. };
  50.  
  51.  
  52.  
  53. char *ProgName;
  54. int ignoreFonts = 0;
  55.  
  56. Display *dpy;
  57.  
  58.  
  59.  
  60. proplist_t readBlackBoxStyle(char *path);
  61.  
  62.  
  63.  
  64. char*
  65. defaultsPathForDomain(char *domain)
  66. {
  67.     char path[1024];
  68.     char *gspath, *tmp;
  69.  
  70.     gspath = getenv("GNUSTEP_USER_ROOT");
  71.     if (gspath) {
  72.     strcpy(path, gspath);
  73.     strcat(path, "/");
  74.     } else {
  75.     char *home;
  76.     
  77.     home = getenv("HOME");
  78.     if (!home) {
  79.         printf("%s:could not get HOME environment variable!\n", ProgName);
  80.         exit(0);
  81.     }
  82.  
  83.     strcpy(path, home);
  84.     strcat(path, "/GNUstep/");
  85.     }
  86.     strcat(path, DEFAULTS_DIR);
  87.     strcat(path, "/");
  88.     strcat(path, domain);
  89.  
  90.     tmp = malloc(strlen(path)+2);
  91.     strcpy(tmp, path);
  92.     
  93.     return tmp;
  94. }
  95.  
  96.  
  97.  
  98. void
  99. hackPathInTexture(proplist_t texture, char *prefix)
  100. {
  101.     proplist_t type;
  102.     char *t;
  103.  
  104.     /* get texture type */
  105.     type = PLGetArrayElement(texture, 0);
  106.     t = PLGetString(type);
  107.     if (t && (strcasecmp(t, "tpixmap")==0
  108.           || strcasecmp(t, "spixmap")==0
  109.           || strcasecmp(t, "mpixmap")==0
  110.           || strcasecmp(t, "cpixmap")==0
  111.           || strcasecmp(t, "tvgradient")==0
  112.           || strcasecmp(t, "thgradient")==0        
  113.           || strcasecmp(t, "tdgradient")==0)) {
  114.     proplist_t file;
  115.     char buffer[4018];
  116.  
  117.     /* get pixmap file path */
  118.     file = PLGetArrayElement(texture, 1);
  119.     sprintf(buffer, "%s/%s", prefix, PLGetString(file));
  120.     /* replace path with full path */
  121.     PLRemoveArrayElement(texture, 1);
  122.     PLInsertArrayElement(texture, PLMakeString(buffer), 1);
  123.     }
  124. }
  125.  
  126.  
  127. void
  128. hackPaths(proplist_t style, char *prefix)
  129. {
  130.     proplist_t keys;
  131.     proplist_t key;
  132.     proplist_t value;
  133.     int i;
  134.  
  135.  
  136.     keys = PLGetAllDictionaryKeys(style);
  137.  
  138.     for (i = 0; i < PLGetNumberOfElements(keys); i++) {
  139.     key = PLGetArrayElement(keys, i);
  140.  
  141.     value = PLGetDictionaryEntry(style, key);
  142.     if (!value)
  143.         continue;
  144.     
  145.     if (strcasecmp(PLGetString(key), "WorkspaceSpecificBack")==0) {
  146.         if (PLIsArray(value)) {
  147.         int j;
  148.         proplist_t texture;
  149.         
  150.         for (j = 0; j < PLGetNumberOfElements(value); j++) {
  151.             texture = PLGetArrayElement(value, j);
  152.  
  153.             if (texture && PLIsArray(texture) 
  154.             && PLGetNumberOfElements(texture) > 2) {
  155.  
  156.             hackPathInTexture(texture, prefix);
  157.             }
  158.         }
  159.         }
  160.     } else {
  161.         
  162.         if (PLIsArray(value) && PLGetNumberOfElements(value) > 2) {
  163.  
  164.         hackPathInTexture(value, prefix);
  165.         }
  166.     }
  167.     }
  168.     
  169. }
  170.  
  171.  
  172. static proplist_t
  173. getColor(proplist_t texture)
  174. {
  175.     proplist_t value, type;
  176.     char *str;
  177.  
  178.     type = PLGetArrayElement(texture, 0);
  179.     if (!type)
  180.     return NULL;
  181.  
  182.     value = NULL;
  183.  
  184.     str = PLGetString(type);
  185.     if (strcasecmp(str, "solid")==0) {
  186.     value = PLGetArrayElement(texture, 1);
  187.     } else if (strcasecmp(str, "dgradient")==0
  188.            || strcasecmp(str, "hgradient")==0
  189.            || strcasecmp(str, "vgradient")==0) {
  190.     proplist_t c1, c2;
  191.     int r1, g1, b1, r2, g2, b2;
  192.     char buffer[32];
  193.  
  194.     c1 = PLGetArrayElement(texture, 1);
  195.     c2 = PLGetArrayElement(texture, 2);
  196.     if (!dpy) {
  197.         if (sscanf(PLGetString(c1), "#%2x%2x%2x", &r1, &g1, &b1)==3
  198.         && sscanf(PLGetString(c2), "#%2x%2x%2x", &r2, &g2, &b2)==3) {
  199.         sprintf(buffer, "#%02x%02x%02x", (r1+r2)/2, (g1+g2)/2,
  200.             (b1+b2)/2);
  201.         value = PLMakeString(buffer);
  202.         } else {
  203.         value = c1;
  204.         }
  205.     } else {
  206.         XColor color1;
  207.         XColor color2;
  208.         
  209.         XParseColor(dpy, DefaultColormap(dpy, DefaultScreen(dpy)), 
  210.             PLGetString(c1), &color1);
  211.         XParseColor(dpy, DefaultColormap(dpy, DefaultScreen(dpy)),
  212.             PLGetString(c2), &color2);
  213.  
  214.         sprintf(buffer, "#%02x%02x%02x", 
  215.             (color1.red+color2.red)>>9,
  216.             (color1.green+color2.green)>>9,
  217.             (color1.blue+color2.blue)>>9);
  218.         value = PLMakeString(buffer);        
  219.     }
  220.     } else if (strcasecmp(str, "mdgradient")==0
  221.            || strcasecmp(str, "mhgradient")==0
  222.            || strcasecmp(str, "mvgradient")==0) {
  223.     
  224.     value = PLGetArrayElement(texture, 1);
  225.  
  226.     } else if (strcasecmp(str, "tpixmap")==0
  227.            || strcasecmp(str, "cpixmap")==0
  228.            || strcasecmp(str, "spixmap")==0) {
  229.     
  230.     value = PLGetArrayElement(texture, 2);
  231.     }
  232.  
  233.     return value;
  234. }
  235.  
  236.  
  237. /*
  238.  * since some of the options introduce incompatibilities, we will need
  239.  * to do a kluge here or the themes ppl will get real annoying.
  240.  * So, treat for the absence of the following options:
  241.  * IconTitleColor
  242.  * IconTitleBack
  243.  */
  244. void
  245. hackStyle(proplist_t style)
  246. {
  247.     proplist_t keys;
  248.     proplist_t tmp;
  249.     int i;
  250.     int foundIconTitle = 0;
  251.     int foundResizebarBack = 0;
  252.  
  253.     keys = PLGetAllDictionaryKeys(style);
  254.  
  255.     for (i = 0; i < PLGetNumberOfElements(keys); i++) {
  256.     char *str;
  257.  
  258.     tmp = PLGetArrayElement(keys, i);
  259.     str = PLGetString(tmp);
  260.     if (str) {
  261.         int j, found;
  262.  
  263.         if (ignoreFonts) {
  264.         for (j = 0, found = 0; FontOptions[j]!=NULL; j++) {
  265.             if (strcasecmp(str, FontOptions[j])==0) {
  266.             PLRemoveDictionaryEntry(style, tmp);
  267.             found = 1;
  268.             break;
  269.             }
  270.         } 
  271.         if (found)
  272.             continue;
  273.         }
  274.  
  275.         if (strcasecmp(str, "IconTitleColor")==0
  276.         || strcasecmp(str, "IconTitleBack")==0) {
  277.         foundIconTitle = 1;
  278.         } else if (strcasecmp(str, "ResizebarBack")==0) {
  279.         foundResizebarBack = 1;
  280.         }
  281.     }
  282.     }
  283.  
  284.     if (!foundIconTitle) {
  285.     /* set the default values */
  286.     tmp = PLGetDictionaryEntry(style, PLMakeString("FTitleColor"));
  287.     if (tmp) {
  288.         PLInsertDictionaryEntry(style, PLMakeString("IconTitleColor"),
  289.                     tmp);
  290.     }
  291.  
  292.     tmp = PLGetDictionaryEntry(style, PLMakeString("FTitleBack"));
  293.     if (tmp) {
  294.         proplist_t value;
  295.  
  296.         value = getColor(tmp);
  297.  
  298.         if (value) {
  299.         PLInsertDictionaryEntry(style, PLMakeString("IconTitleBack"),
  300.                     value);
  301.         }
  302.     }
  303.     }
  304.  
  305.     if (!foundResizebarBack) {
  306.     /* set the default values */
  307.     tmp = PLGetDictionaryEntry(style, PLMakeString("UTitleBack"));
  308.     if (tmp) {
  309.         proplist_t value;
  310.  
  311.         value = getColor(tmp);
  312.  
  313.         if (value) {
  314.         proplist_t t;
  315.         
  316.         t = PLMakeArrayFromElements(PLMakeString("solid"), value, 
  317.                         NULL);
  318.         PLInsertDictionaryEntry(style, PLMakeString("ResizebarBack"),
  319.                     t);
  320.         }
  321.     }
  322.     }
  323.  
  324.  
  325.     if (!PLGetDictionaryEntry(style, PLMakeString("MenuStyle"))) {
  326.     PLInsertDictionaryEntry(style, PLMakeString("MenuStyle"),
  327.                 PLMakeString("normal"));
  328.     }
  329. }
  330.  
  331.  
  332. BOOL
  333. StringCompareHook(proplist_t pl1, proplist_t pl2)
  334. {
  335.     char *str1, *str2;
  336.  
  337.     str1 = PLGetString(pl1);
  338.     str2 = PLGetString(pl2);
  339.  
  340.     if (strcasecmp(str1, str2)==0)
  341.       return YES;
  342.     else
  343.       return NO;
  344. }
  345.  
  346.  
  347. void
  348. print_help()
  349. {
  350.     printf("Usage: %s [OPTIONS] FILE\n", ProgName);
  351.     puts("Reads style/theme configuration from FILE and updates Window Maker.");
  352.     puts("");
  353.     puts("  --no-fonts        ignore font related options");
  354.     puts("  --ignore <option>    ignore changes in the specified option");
  355.     puts("  --help        display this help and exit");
  356.     /*
  357.     puts("  --format <format>    specifies the format of the theme to be converted");
  358.      */
  359.     puts("  --version        output version information and exit");
  360.     puts("");
  361.     puts("Supported formats: blackbox");
  362. }
  363.  
  364.  
  365. #define F_BLACKBOX    1
  366.  
  367. int 
  368. main(int argc, char **argv)
  369. {
  370.     proplist_t prop, style;
  371.     char *path;
  372.     char *file = NULL;
  373.     struct stat statbuf;
  374.     int i;
  375.     int ignoreCount = 0;
  376.     char *ignoreList[MAX_OPTIONS];
  377.  
  378.     dpy = XOpenDisplay("");
  379.  
  380.     ProgName = argv[0];
  381.     
  382.     if (argc<2) {
  383.     printf("%s: missing argument\n", ProgName);
  384.     printf("Try '%s --help' for more information\n", ProgName);
  385.     exit(1);
  386.     }
  387.  
  388.     for (i = 1; i < argc; i++) {
  389.     if (strcmp("--ignore", argv[i])==0) {
  390.         i++;
  391.         if (i == argc) {
  392.         printf("%s: missing argument for option --ignore\n", ProgName);
  393.         exit(1);
  394.         }
  395.         ignoreList[ignoreCount++] = argv[i];
  396.  
  397.     } else if (strcmp("--no-fonts", argv[i])==0) {
  398.         ignoreFonts = 1;
  399.     } else if (strcmp("--version", argv[i])==0) {
  400.         puts(PROG_VERSION);
  401.         exit(0);
  402.     } else if (strcmp("--help", argv[i])==0) {
  403.         print_help();
  404.         exit(0);
  405. #if 0
  406.     } else if (strcmp("--format", argv[i])==0) {
  407.         i++;
  408.         if (i == argc) {
  409.         printf("%s: missing argument for option --format\n", ProgName);
  410.         exit(1);
  411.         }
  412.         if (strcasecmp(argv[i], "blackbox")==0) {
  413.         format = F_BLACKBOX;
  414.         } else {
  415.         printf("%s: unknown theme format '%s'\n", ProgName, argv[i]);
  416.         exit(1);
  417.         }
  418. #endif
  419.     } else {
  420.         if (file) {
  421.         printf("%s: invalid argument '%s'\n", ProgName, argv[i]);
  422.         printf("Try '%s --help' for more information\n", ProgName);
  423.         exit(1);
  424.         }
  425.         file = argv[i];
  426.     }
  427.     }
  428.  
  429.     PLSetStringCmpHook(StringCompareHook);
  430.  
  431.     path = defaultsPathForDomain("WindowMaker");
  432.  
  433.     prop = PLGetProplistWithPath(path);
  434.     if (!prop) {
  435.     perror(path);
  436.     printf("%s:could not load WindowMaker configuration file.\n",
  437.            ProgName);
  438.     exit(1);
  439.     }
  440.  
  441.     if (stat(file, &statbuf) < 0) {
  442.     perror(file);
  443.     exit(1);
  444.     }
  445. #if 0
  446.     if (format == F_BLACKBOX) {
  447.     style = readBlackBoxStyle(file);
  448.     if (!style) {
  449.         printf("%s: could not open style file\n", ProgName);
  450.         exit(1);
  451.     }
  452.     } else
  453. #endif
  454.  {
  455.     if (S_ISDIR(statbuf.st_mode)) {
  456.         char buffer[4018];
  457.         char *prefix;
  458.         /* theme pack */
  459.  
  460.         if (*argv[argc-1] != '/') {
  461.         if (!getcwd(buffer, 4000)) {
  462.             printf("%s: complete path for %s is too long\n", ProgName,
  463.                file);
  464.             exit(1);
  465.         }
  466.         if (strlen(buffer) + strlen(file) > 4000) {
  467.             printf("%s: complete path for %s is too long\n", ProgName,
  468.                file);
  469.             exit(1);
  470.         }
  471.         strcat(buffer, "/");
  472.         } else {
  473.         buffer[0] = 0;
  474.         }
  475.         strcat(buffer, file);
  476.         
  477.         prefix = malloc(strlen(buffer)+10);
  478.         if (!prefix) {
  479.         printf("%s: out of memory\n", ProgName);
  480.         exit(1);
  481.         }
  482.         strcpy(prefix, buffer);
  483.  
  484.         strcat(buffer, "/style");
  485.     
  486.         style = PLGetProplistWithPath(buffer);
  487.         if (!style) {
  488.         perror(buffer);
  489.         printf("%s:could not load style file.\n", ProgName);
  490.         exit(1);
  491.         }
  492.  
  493.         hackPaths(style, prefix);
  494.         free(prefix);
  495.     } else {
  496.         /* normal style file */
  497.         
  498.         style = PLGetProplistWithPath(file);
  499.         if (!style) {
  500.         perror(file);
  501.         printf("%s:could not load style file.\n", ProgName);
  502.         exit(1);
  503.         }
  504.     }
  505.     }
  506.     
  507.     if (!PLIsDictionary(style)) {
  508.     printf("%s: '%s' is not a style file/theme\n", ProgName, file);
  509.     exit(1);
  510.     }
  511.  
  512.     hackStyle(style);
  513.  
  514.     if (ignoreCount > 0) {
  515.     for (i = 0; i < ignoreCount; i++) {
  516.         PLRemoveDictionaryEntry(style, PLMakeString(ignoreList[i]));
  517.     }
  518.     }
  519.  
  520.     PLMergeDictionaries(prop, style);
  521.  
  522.     PLSave(prop, YES);
  523.     {
  524.     XEvent ev;
  525.     
  526.     if (dpy) {
  527.         int i;
  528.         char *msg = "Reconfigure";
  529.  
  530.         memset(&ev, 0, sizeof(XEvent));
  531.         
  532.         ev.xclient.type = ClientMessage;
  533.         ev.xclient.message_type = XInternAtom(dpy, "_WINDOWMAKER_COMMAND",
  534.                           False);
  535.         ev.xclient.window = DefaultRootWindow(dpy);
  536.         ev.xclient.format = 8;
  537.  
  538.         for (i = 0; i <= strlen(msg); i++) {
  539.         ev.xclient.data.b[i] = msg[i];
  540.         }
  541.         XSendEvent(dpy, DefaultRootWindow(dpy), False, 
  542.                SubstructureRedirectMask, &ev);
  543.         XFlush(dpy);
  544.     }
  545.     }
  546.  
  547.     exit(0);
  548. }
  549.  
  550.  
  551. #if 0
  552. char*
  553. getToken(char *str, int i, char *buf)
  554. {
  555.     
  556. }
  557.  
  558.  
  559. proplist_t
  560. readBlackBoxStyle(char *path)
  561. {
  562.     FILE *f;
  563.     char buffer[128], char token[128];
  564.     proplist_t style;
  565.     proplist_t p;
  566.     
  567.     f = fopen(path, "r");
  568.     if (!f) {
  569.     perror(path);
  570.     return NULL;
  571.     }
  572.  
  573.     while (1) {
  574.     if (!fgets(buffer, 127, f))
  575.         break;
  576.  
  577.     if (strncasecmp(buffer, "menu.title:", 11)==0) {
  578.         
  579.     }
  580.     }
  581. }
  582. #endif
  583.